package com

import com.Main.Companion.runPath
import com.XferMgrProgress.waitForCompletion
import com.amazonaws.ClientConfiguration
import com.amazonaws.auth.AWSStaticCredentialsProvider
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.regions.Regions
import com.amazonaws.services.s3.AmazonS3ClientBuilder
import com.amazonaws.services.s3.internal.Mimetypes
import com.amazonaws.services.s3.model.*
import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion
import com.amazonaws.services.s3.transfer.MultipleFileUpload
import com.amazonaws.services.s3.transfer.MyTransferManager
import com.amazonaws.services.s3.transfer.MyTransferManagerBuilder.Companion.standard
import com.amazonaws.services.s3.transfer.Transfer
import com.amazonaws.services.s3.transfer.internal.MyUploadImpl
import java.io.File
import kotlin.io.path.Path
import kotlin.io.path.pathString
import kotlin.io.path.readText
import kotlin.test.Test

class AWSTest {

    private var transferManager: MyTransferManager? = null
    var awsStaticCredentialsProvider: AWSStaticCredentialsProvider? = null
        get() {
            if (field == null) {
                val awsCreds = BasicAWSCredentials(
                    Config.dataManage!!.packCmd.accessKeyId,
                    Config.dataManage!!.packCmd.accessKeySecret
                )
                field = AWSStaticCredentialsProvider(awsCreds)
            }
            return field
        }
        private set
    private var consolePro: ConsoleProgressBar? = null


    @Test
    fun packTest() {

        Main.main(arrayOf("-r", "D:\\WorkSpace\\Idea\\Java\\AWSPush\\test.txt"))

    }


    @Test
    fun test() {
        val dataManage = AwsUtils()
        dataManage.packCmd.profile = ".aws_user2"
        dataManage.checkAccount()

        println(dataManage.packCmd.accessKeyId + ", " + dataManage.packCmd.accessKeySecret)

        System.setProperty("runPath", runPath.pathString)

        val bucketName = "bucketName"
        //        listObjectsV2(bucketName);
        listKeysVersioning(bucketName)

        //        uploadFile(bucketName);

//        URL url = Loader.getResource("log4j.properties");
//        System.out.println(url);

//        setObjectAcl(bucketName);
    }

    private fun listObjectsV2(bucketName: String) {
        val s3Client = AmazonS3ClientBuilder.standard()
            .withRegion(Regions.EU_CENTRAL_1)
            .withCredentials(awsStaticCredentialsProvider)
            .build()

        val request = ListObjectsV2Request()
        request.bucketName = bucketName

        for (j in 0..49) {
            val bn = s3Client.listObjectsV2(request)

            val list = bn.objectSummaries

            println(list.size)

            val deleteList: MutableList<KeyVersion> = ArrayList()

            for (i in list.indices) {
                println(list.get(i).key)
                if (list[i].key.startsWith("bucketName")) {
                    deleteList.add(KeyVersion(list[i].key))
                }
            }

            println("删除数量=" + deleteList.size)

            val deleteObjectsResult = DeleteObjectsRequest(bucketName)
                .withKeys(deleteList)
            s3Client.deleteObjects(deleteObjectsResult)
        }
    }

    private fun listKeysVersioning(bucketName: String) {
        val s3Client = AmazonS3ClientBuilder.standard()
            .withRegion(Regions.EU_CENTRAL_1)
            .withCredentials(awsStaticCredentialsProvider)
            .build()

        transferManager = standard()
            .withS3Client(s3Client)
            .build()

        val copyObjectRequest: CopyObjectRequest? = null

        //        copyObjectRequest = new CopyObjectRequest(bucketName, "", "", bucketName, "");
//        transferManager.copy(copyObjectRequest);
        val request = ListVersionsRequest()
            .withBucketName(bucketName)
            .withMaxResults(2)
        var versionListing = s3Client.listVersions(request)


        var numVersions = 0
        var numPages = 0
        while (true) {
            numPages++
            for (objectSummary in versionListing.versionSummaries) {
                System.out.printf(
                    "Retrieved object %s, version %s, lastmodified %s, tag %s\n",
                    objectSummary.key,
                    objectSummary.versionId,
                    objectSummary.lastModified,
                    objectSummary.eTag
                )
                numVersions++
            }
            // Check whether there are more pages of versions to retrieve. If
            // there are, retrieve them. Otherwise, exit the loop.
            if (versionListing.isTruncated) {
                versionListing = s3Client.listNextBatchOfVersions(versionListing)
            } else {
                break
            }
        }
        println("$numVersions object versions retrieved in $numPages pages")
    }

    fun setObjectAcl(bucketName: String?) {
        val clientConfig = ClientConfiguration()
        clientConfig.withProxyHost("47.91.188.247")
        clientConfig.withProxyPort(27017)
        clientConfig.withProxyUsername("47.91.188.247")
        clientConfig.withProxyPassword("Mania.Rambo")

        //        clientConfig.withDisableSocketProxy(false);
        val s3Client = AmazonS3ClientBuilder.standard()
            .withRegion(Regions.EU_CENTRAL_1)
            .withClientConfiguration(clientConfig)
            .withCredentials(awsStaticCredentialsProvider)
            .build()


        val ol = s3Client.listObjects(bucketName)
        val objects = ol.objectSummaries
        println(" len = " + objects.size)
        for (os in objects) {
//            System.out.println("* " + os.getKey());
            s3Client.setObjectAcl(
                bucketName,
                os.key,  //                    CannedAccessControlList.Private
                CannedAccessControlList.PublicRead
            )
        }
    }


    fun uploadFile(bucketName: String?) {
        val s3Client = AmazonS3ClientBuilder.standard()
            .withRegion(Regions.EU_CENTRAL_1)
            .withCredentials(awsStaticCredentialsProvider)
            .build()

        transferManager = standard()
            .withS3Client(s3Client)
            .build()

        val list: MutableList<File?> = ArrayList()
        list.add(File("/Users/boge/Project/AWSGame/WonderGame/Static2-Project/wapGame/WonderGame.max.min.js"))
        list.add(File("/Users/boge/Project/AWSGame/WonderGame/Static2-Project/wapGame/game.min.js"))
        list.add(File("/Users/boge/Project/AWSGame/WonderGame/Static2-Project/wapGame/config.min.js"))

        consolePro = ConsoleProgressBar(0, list.size.toLong(), 20)

        val parentFile = "res"
        val absoluteFile = File("/Users/boge/Project/AWSGame/WonderGame/Static2-Project/")

        val xfer = transferManager!!.uploadFileList(
            bucketName,
            parentFile,
            absoluteFile,
            list, { file: File, objectMetadata: ObjectMetadata ->
//                    if (file.getName().contains(".js")) {
                objectMetadata.contentLength = file.length()
                objectMetadata.contentType = Mimetypes.getInstance().getMimetype(file)
            }, CannedAccessControlList.PublicRead
        )
        println(xfer)

        // loop with Transfer.isDone()
        showMultiUploadProgress(xfer)
        //        showTransferProgress(xfer);
        // or block with Transfer.waitForCompletion()
        waitForCompletion(xfer)
    }


    // Prints progress while waiting for the transfer to finish.
    private fun showTransferProgress(xfer: Transfer) {
        // print the transfer's human-readable description
        println(xfer.description)
        do {
            try {
                Thread.sleep(100)
            } catch (e: InterruptedException) {
                return
            }
            // Note: so_far and total aren't used, they're just for
            // documentation purposes.
            val progress = xfer.progress
            val so_far = progress.bytesTransferred
            val total = progress.totalBytesToTransfer
            val pct = progress.percentTransferred
            val pro = pct.toLong()
            consolePro!!.show(pro)
        } while (!xfer.isDone)
        // print the final state of the transfer.
        val xfer_state = xfer.state
        println(" ")
        println("upload $xfer_state")
    }


    companion object {
        fun showMultiUploadProgress(multi_upload: MultipleFileUpload) {
            // print the upload's human-readable description
            println(multi_upload.description)

            val sub_xfers = multi_upload.subTransfers

            do {
                println("\nSubtransfer progress:\n")
                for (u in sub_xfers) {
                    println("  " + (u as MyUploadImpl).putObjectRequest.key)
                    if (u.isDone()) {
                        val xfer_state = u.getState()
                        //                    System.out.println("  " + xfer_state);
                    } else {
                        val progress = u.getProgress()
                        val pct = progress.percentTransferred
                        //                    printProgressBar(pct);
                        println(pct)
                    }
                }

                // wait a bit before the next update.
                try {
                    Thread.sleep(200)
                } catch (e: InterruptedException) {
                    return
                }
            } while (multi_upload.isDone == false)
            // print the final state of the transfer.
            val xfer_state = multi_upload.state
            println("\nMultipleFileUpload $xfer_state")
        }
    }


}
